/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package eu.easyedu.dictionary.api.util;

import eu.easyedu.dictionary.api.model.Dictionary;
import eu.easyedu.dictionary.api.model.Language;
import eu.easyedu.dictionary.api.nservice.spi.DictionaryService;
import eu.easyedu.dictionary.api.nservice.spi.WordBookService;
import eu.easyedu.dictionary.api.service.events.DictionaryEventListener;
import eu.easyedu.dictionary.explorer.AddDictionaryDialog;
import eu.easyedu.dictionary.explorer.DictionaryList;
import eu.easyedu.dictionary.api.options.DictionaryOptions;
import java.awt.Frame;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.IOException;
import java.util.Collection;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.netbeans.api.db.explorer.ConnectionManager;
import org.netbeans.api.db.explorer.DatabaseConnection;
import org.netbeans.api.db.explorer.DatabaseException;
import org.netbeans.api.progress.ProgressHandle;
import org.netbeans.api.progress.ProgressHandleFactory;
import org.openide.util.Exceptions;
import org.openide.util.Lookup;
import org.openide.util.RequestProcessor;
import org.openide.windows.WindowManager;

/**
 *
 * @author hlavki
 */
public class DictionaryManager {

    private static DictionaryManager instance;
    private static final Logger log = Logger.getLogger(DictionaryManager.class.getName());
    public static final String PROPERTY_DEFAULT_DICTIONARY = "defaultDictionary";
    private PropertyChangeSupport changeSupport;

    private DictionaryManager() {
        changeSupport = new PropertyChangeSupport(this);
    }

    public final static synchronized DictionaryManager getDefault() {
        if (instance == null) {
            instance = new DictionaryManager();
        }
        return instance;
    }

    public void addDictionary(Dictionary dictionary, Language lang, boolean createDDL, ProgressHandle handle) {
        try {
            if (createDDL) {
                DictionaryService dictionaryService = Lookup.getDefault().lookup(DictionaryService.class);
                handle.progress("Generating DDL...");
                dictionaryService.createDictionaryDDL(dictionary);
                handle.progress("");
            }
            DictionaryList.getDefault().add(dictionary);
            if (lang != null) {
                WordBookService wordBookService = Lookup.getDefault().lookup(WordBookService.class);
                wordBookService.addLanguage(dictionary, lang);
            }
            // if first dictionary, set as default
            if (DictionaryList.getDefault().getDictionaries().size() == 1) {
                DictionaryManager.getDefault().setDefaultDictionary(dictionary);
            }
        } catch (Exception e) {
            log.warning(e.getMessage());
            Exceptions.printStackTrace(e);
        }
    }

    public void removeDictionary(Dictionary dictionary) {
        try {
            DictionaryList.getDefault().remove(dictionary);
            DatabaseUtils.removeConnection(dictionary);
        } catch (IOException e) {
            log.warning(e.getMessage());
            Exceptions.printStackTrace(e);
        }
    }

    public Dictionary getDefaultDictionary() {
        return DictionaryOptions.getInstance().getDefaultDictionary();
    }

    public Dictionary getDictionary(String connectionName) {
        Collection<? extends Dictionary> dictionaries = DictionaryList.getDefault().getDictionaries();
        for (Dictionary dictionary : dictionaries) {
            if (dictionary.getConnectionName().equals(connectionName)) {
                return dictionary;
            }
        }
        return null;
    }

    public void setDefaultDictionary(Dictionary dictionary) {
        DictionaryOptions.getInstance().setDefaultDictionary(dictionary);
        changeSupport.firePropertyChange(PROPERTY_DEFAULT_DICTIONARY, null, null);
    }

    public void showAddDictionaryDialog() throws ConnectionDoesNotExistsException {
        Frame mainWindow = WindowManager.getDefault().getMainWindow();
        AddDictionaryDialog dialog = new AddDictionaryDialog(mainWindow, true);
        dialog.setLocationRelativeTo(mainWindow);
        dialog.setVisible(true);
        if (dialog.isPrepared()) {
            final Language language = dialog.getLanguage();
            String dictionaryName = dialog.getDictionaryName();
            final boolean createDDL = dialog.createDictionary();
            DatabaseConnection conn = createConnection(dialog.getDerbyDriver(), dialog.getUrl());
            final Dictionary dictionary = new Dictionary(dictionaryName, conn.getName());
            DatabaseUtils.getConnection(dictionary).getJDBCConnection();
            conn.getJDBCConnection();
            RequestProcessor.getDefault().post(new Runnable() {

                public void run() {
                    ProgressHandle handle = ProgressHandleFactory.createHandle("Creating dictionary...");
                    handle.start();
                    addDictionary(dictionary, language, createDDL, handle);
                    handle.finish();
                }
            });
        }
    }

    /**
     * Registers a DictionaryEventListener.
     */
    public void addDictionaryEventListener(DictionaryEventListener listener) {
        DictionaryList.getDefault().addDictionaryEventListener(listener);
    }

    /**
     * Unregisters the specified dictionary listener.
     */
    public void removeDictionaryEventListener(DictionaryEventListener listener) {
        DictionaryList.getDefault().removeDictionaryEventListener(listener);
    }

    public void addPropertyChangeListener(PropertyChangeListener l) {
        changeSupport.addPropertyChangeListener(l);
    }

    public void removePropertyChangeListener(PropertyChangeListener l) {
        changeSupport.removePropertyChangeListener(l);
    }

    public DatabaseConnection createConnection(DerbyDriver driver, String url) {
        DatabaseConnection conn = DatabaseConnection.create(DatabaseUtils.getDriver(driver.getDriverClass()),
                url, "app", "APP", "app", true);
        try {
            ConnectionManager.getDefault().addConnection(conn);
        } catch (DatabaseException e) {
            log.log(Level.WARNING, e.getMessage(), e);
            conn = null;
        }
        return conn;
    }
}
